#include <stdlib.h>
#include <stdio.h>
#include <upnp/upnp.h>
#include <upnp/upnptools.h>

#include "urobot.h"
#include "services.h"
#include "urobot.h"
#include "services.h"
#include "mime.h"
#include "buffer.h"
#include "utils.h"
#include "trace.h" 
#include "cam.h" 
#include "target.h" 

/* Represent the CAM GetSystemUpdateID action. */
#define SERVICE_CAM_ACTION_UPDATE_ID "GetSystemUpdateID"

/* Represent the CAM SetEncoding action. */
#define SERVICE_CAM_ACTION_SET_ENCODING "SetEncoding"

/* Represent the CAM GetEncoding action. */
#define SERVICE_CAM_ACTION_GET_ENCODING "SetEncoding"

/* Represent the CAM SetResolution action. */
#define SERVICE_CAM_ACTION_SET_RESOLUTION "SetResolution"

/* Represent the CAM GetResolution action. */
#define SERVICE_CAM_ACTION_GET_RESOLUTION "GetResolution"

/* Represent the CAM GetVideoURL action. */
#define SERVICE_CAM_ACTION_GET_VIDEO_URL "GetVideoURL"

/* Represent the CAM SetFrameRate action. */
#define SERVICE_CAM_ACTION_SET_FRAME_RATE "SetFrameRate"

/* Represent the CAM GetFrameRate action. */
#define SERVICE_CAM_ACTION_GET_FRAME_RATE "GetFrameRate"

/* Represent the CAM UpdateId argument. */
#define SERVICE_CAM_ARG_UPDATE_ID "UpdateID"

/* Represent the CAM Encoding argument. */
#define SERVICE_CAM_ARG_ENCODING "Encoding"

/* Represent the CAM Resolution argument. */
#define SERVICE_CAM_ARG_RESOLUTION "Resolution"

/* Represent the CAM CameraIndex argument. */
#define SERVICE_CAM_ARG_CAMERA_INDEX "CameraIndex"

/* Represent the CAM CameraType argument. */
#define SERVICE_CAM_ARG_CAMERA_TYPE "CameraType"

/* Represent the CAM FrameRate argument. */
#define SERVICE_CAM_ARG_FRAME_RATE "FrameRate"

/* Represent the CAM CameraType argument. */
#define SERVICE_CAM_ARG_VIDEO_URL "VideoURL"

/* Represent the CAM ObjectID argument. */
#define SERVICE_CAM_ARG_OBJECT_ID "ObjectID"

/* Represent the CAM Root Object ID argument. */
#define SERVICE_CAM_ROOT_OBJECT_ID "0"

/* Represent the CAM Status argument. */
#define SERVICE_CAM_ARG_STATUS "Status"

/* Represent the CAM Status value. */
#define SERVICE_CAM_STATUS_OK "OK"

static bool
cam_get_system_update_id (struct action_event_t *event)
{
  upnp_add_response (event, SERVICE_CAM_ARG_UPDATE_ID,
                     SERVICE_CAM_ROOT_OBJECT_ID);

  return event->status;
}

static bool
cam_set_encoding (struct action_event_t *event)
{
  int result_count;
  int action = 0;
  char tmp_encoding[20];
  char *encoding = NULL;

  /* Retrieve Browse arguments */
  encoding = upnp_get_string (event->request, SERVICE_CAM_ARG_ENCODING);

  // set encoding
  result_count = get_camera_data (0, &action, tmp_encoding);
  result_count = set_camera_data (0, action, encoding);

  upnp_add_response (event, SERVICE_CAM_ARG_STATUS, SERVICE_CAM_STATUS_OK);

  return event->status;
}

static bool
cam_get_encoding (struct action_event_t *event)
{
  int index, action, result_count;
  char encoding[20];

  /* Retrieve Browse arguments */
  index = upnp_get_ui4 (event->request, SERVICE_CAM_ARG_CAMERA_INDEX);

  result_count = get_camera_data (index, &action, encoding);
  upnp_add_response (event, SERVICE_CAM_ARG_ENCODING, encoding);

  return event->status;
}

static bool
cam_set_resolution (struct action_event_t *event)
{
  // set resolution

  upnp_add_response (event, SERVICE_CAM_ARG_STATUS, SERVICE_CAM_STATUS_OK);

  return event->status;
}

static bool
cam_get_resolution (struct action_event_t *event)
{
  char *resolution;

  upnp_add_response (event, SERVICE_CAM_ARG_RESOLUTION, resolution);

  return event->status;
}

  
int
cam_browse_metadata (struct buffer_t *out, int index, int type)
{
  extern struct urobot_t *ut;
  int result_count = 0;
  int tmp_type;
  char encoding[20];
  char url[30];

  result_count = get_camera_data (index, &tmp_type, encoding);
  sprintf(url, "?action=%s/"/*&id=%d"*/, type == 0 ? "stream":"snapshot"/*, index*/);
  buffer_appendf (out, "http://%s:%d/%s",
                      UpnpGetServerIpAddress (), CAM_PORT/*ut->port*/, url);
    
  return result_count;
}

static bool
cam_get_video_url (struct action_event_t *event)
{
  extern struct urobot_t *ut;
  int result_count = 0, index, type, id;
  struct buffer_t *out = NULL;

  if (!event)
    return false;

  /* Check for status */
  if (!event->status)
    return false;

  /* check if metadatas have been well inited */
  if (!ut->init)
    return false;

  /* Retrieve Browse arguments */
  index = upnp_get_ui4 (event->request, SERVICE_CAM_ARG_CAMERA_INDEX);
  type = upnp_get_ui4 (event->request, SERVICE_CAM_ARG_CAMERA_TYPE);
  id = upnp_get_ui4 (event->request, SERVICE_CAM_ARG_OBJECT_ID);

  out = buffer_new ();
  if (!out)
  {
    return false;
  }

  result_count = cam_browse_metadata (out, index, type);
  printf("VideoURL=%s, result_count=%d\n", out->buf, result_count);

  if (result_count < 0)
  {
    buffer_free (out);
    return false;
  }

  upnp_add_response (event, SERVICE_CAM_ARG_VIDEO_URL, out->buf);
  buffer_free (out);

  return event->status;
}

static bool
cam_set_frame_rate (struct action_event_t *event)
{
  // set frame rate

  upnp_add_response (event, SERVICE_CAM_ARG_STATUS, SERVICE_CAM_STATUS_OK);

  return event->status;
}

static bool
cam_get_frame_rate (struct action_event_t *event)
{
  char *frame_rate;

  upnp_add_response (event, SERVICE_CAM_ARG_FRAME_RATE, frame_rate);

  return event->status;
}

/* List of UPnP ContentDirectory Service actions */
struct service_action_t cam_service_actions[] = {
  { SERVICE_CAM_ACTION_UPDATE_ID, cam_get_system_update_id },
  { SERVICE_CAM_ACTION_GET_VIDEO_URL, cam_get_video_url },
  { SERVICE_CAM_ACTION_GET_ENCODING, cam_get_encoding },
  { SERVICE_CAM_ACTION_SET_ENCODING, cam_set_encoding },
  { SERVICE_CAM_ACTION_GET_RESOLUTION, cam_get_resolution },
  { SERVICE_CAM_ACTION_SET_RESOLUTION, cam_set_resolution },
  { SERVICE_CAM_ACTION_GET_FRAME_RATE, cam_get_frame_rate },
  { SERVICE_CAM_ACTION_SET_FRAME_RATE, cam_set_frame_rate },
  { NULL, NULL }
};
